package com.example.lib_common.logger

import android.os.Handler
import android.os.HandlerThread
import com.orhanobut.logger.DiskLogStrategy
import com.orhanobut.logger.FormatStrategy
import com.orhanobut.logger.LogStrategy
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale


class MyCsvFormatStrategy private constructor(builder: Builder) : FormatStrategy {
    private val date: Date
    private val dateFormat: SimpleDateFormat
    private val logStrategy: LogStrategy
    private val tag: String?

    init {
        LoggerUtils.checkNotNull<Builder?>(builder)

        date = builder.date!!
        dateFormat = builder.dateFormat!!
        logStrategy = builder.logStrategy!!
        tag = builder.tag
    }

    override fun log(priority: Int, onceOnlyTag: String?, message: String) {
        var message = message
        LoggerUtils.checkNotNull<String?>(message)

        val tag = formatTag(onceOnlyTag)

        date.setTime(System.currentTimeMillis())

        val builder = StringBuilder()

        // machine-readable date/time
        builder.append(date.getTime().toString())

        // human-readable date/time
        builder.append(SEPARATOR)
        builder.append(dateFormat.format(date))

        // level
        builder.append(SEPARATOR)
        builder.append(LoggerUtils.logLevel(priority))

        // tag
        builder.append(SEPARATOR)
        builder.append(tag)

        // message
        if (message.contains(NEW_LINE)) {
            // a new line would break the CSV format, so we replace it here
            message = message.replace(NEW_LINE.toRegex(), NEW_LINE_REPLACEMENT)
        }
        builder.append(SEPARATOR)
        builder.append(message)

        // new line
        builder.append(NEW_LINE)

        logStrategy.log(priority, tag, builder.toString())
    }

    private fun formatTag(tag: String?): String? {
        if (!LoggerUtils.isEmpty(tag) && !LoggerUtils.equals(this.tag, tag)) {
            return this.tag + "-" + tag
        }
        return this.tag
    }

    class Builder constructor() {
        var savePath = ""
        var date: Date? = null
        var dateFormat: SimpleDateFormat? = null
        var logStrategy: LogStrategy? = null
        var tag: String? = "PRETTY_LOGGER"

        fun date(`val`: Date?): Builder {
            date = `val`
            return this
        }

        fun dateFormat(`val`: SimpleDateFormat?): Builder {
            dateFormat = `val`
            return this
        }

        fun logStrategy(`val`: LogStrategy?): Builder {
            logStrategy = `val`
            return this
        }

        fun tag(tag: String?): Builder {
            this.tag = tag
            return this
        }

        fun savePath(path: String): Builder {
            this.savePath = path
            return this
        }

        fun build(): MyCsvFormatStrategy {
            if (date == null) {
                date = Date()
            }
            if (dateFormat == null) {
                dateFormat = SimpleDateFormat("yyyy.MM.dd HH:mm:ss.SSS", Locale.UK)
            }
            if (logStrategy == null) {
//                val diskPath = Environment.getExternalStorageDirectory().getAbsolutePath()
//                val folder = diskPath + File.separatorChar + "logger"

                val ht = HandlerThread("AndroidFileLogger." + savePath)
                ht.start()
                val handler: Handler = LoggerWriteHandler(ht.getLooper(), savePath, MAX_BYTES)
                logStrategy = DiskLogStrategy(handler)
            }
            return MyCsvFormatStrategy(this)
        }

        companion object {
            private val MAX_BYTES = 500 * 1024 // 500K averages to a 4000 lines per file
        }


    }

    companion object {
        private val NEW_LINE: String = System.lineSeparator()
        private const val NEW_LINE_REPLACEMENT = " <br> "
        private const val SEPARATOR = ","

        fun newBuilder(): Builder {
            return MyCsvFormatStrategy.Builder()
        }
    }
}

